home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1986 Norm Hutchinson. May not be used for any *
- * purpose without written permission from the author. */
-
- #include "Kernel/h/assert.h"
- #include "Kernel/h/system.h"
- #include "Kernel/h/map96.h"
-
- #define INITIALSIZE 16
-
- #define HASH(key0, key1, key2, map) \
- ((((key0) << 1) ^ ((key1) >> 3) ^ ((key2) >> 6)) & map->maxIndex)
- static void CheckOutHashTable();
-
- #define MAXMAPSTANDBY 20
- int nextFreeMap96 = 0;
- Map96 standbyMap96s[MAXMAPSTANDBY];
-
- #ifdef DEBUGMAP
- int inhibitCheck = 0;
- #endif
-
- Map96 Map96_Create()
- {
- register int i;
- register Map96 m;
- register TE96Ptr entryPtr;
- register int myNil = NIL;
-
- if (nextFreeMap96 > 0) {
- /* Grab one from standby stack */
- m = standbyMap96s[--nextFreeMap96];
- return m;
- }
-
- /* Allocate a new one */
- m = (Map96) malloc(sizeof(Map96Record));
- m->table = (TE96Ptr) malloc(INITIALSIZE * sizeof(TE96));
- m->maxIndex = INITIALSIZE - 1;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
- m->count = 0;
- i = m->maxIndex;
- entryPtr = &m->table[i+1];
- do {
- (--entryPtr)->key0 = myNil;
- } while (--i >= 0);
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return(m);
- }
-
- Map96 Map96_CreateSized(fCount)
- int fCount;
- {
- register int i;
- register Map96 m;
- register TE96Ptr entryPtr;
- register int myNil = NIL;
-
- assert(fCount > 0);
- m = (Map96) malloc(sizeof(Map96Record));
- /* Make i the first power of two greater than fCount */
- for (i = 1; i <= fCount; i += i);
- i--;
- m->maxIndex = i;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
- m->count = 0;
- m->table = (TE96Ptr) malloc((unsigned)((m->maxIndex+1) * sizeof(TE96)));
- entryPtr = &m->table[i+1];
- do {
- (--entryPtr)->key0 = myNil;
- } while (--i >= 0);
- # ifdef lint
- CheckOutHashTable(m);
- #endif
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return(m);
- }
-
- void Map96_Clear(m)
- register Map96 m;
- {
- register int i;
- register TE96Ptr entryPtr;
- register int myNil = NIL;
-
- m->count = 0;
- i = m->maxIndex;
- entryPtr = &m->table[i+1];
- do {
- (--entryPtr)->key0 = myNil;
- } while (--i >= 0);
- }
-
- void Map96_Destroy(m)
- register Map96 m;
- {
- register int i;
- register TE96Ptr entryPtr;
- register int myNil = NIL;
-
- if (m == (Map96) NULL) return;
- if ((nextFreeMap96 < MAXMAPSTANDBY)
- && (m->maxIndex == INITIALSIZE - 1)
- ) {
- if (m->count != 0) {
- /* Reinitialize it */
- m->count = 0;
- i = m->maxIndex;
- entryPtr = &m->table[i+1];
- do {
- (--entryPtr)->key0 = myNil;
- } while (--i >= 0);
- }
-
- /* Nice map, recycle it */
- standbyMap96s[nextFreeMap96++] = m;
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return;
- }
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- free((char *)m->table);
- free((char *)m);
- }
-
- static void ExpandHashTable(m)
- register Map96 m;
- {
- register TE96 *nh, *oe, *ne;
- register int oldHashTableSize = m->maxIndex + 1, i;
- register int index;
- register int key0, key1, key2;
-
- m->maxIndex = oldHashTableSize * 2 - 1;
- m->maxCount = m->maxIndex - (m->maxIndex >> 2);
- nh = (TE96Ptr) malloc((unsigned)(oldHashTableSize * 2 * sizeof(TE96)));
- for (i = 0; i <= m->maxIndex; i++) nh[i].key0 = NIL;
- for (i = 0; i < oldHashTableSize; i++) {
- oe = &m->table[i];
- key0 = oe->key0;
- if (key0 == NIL) continue;
- key1 = oe->key1;
- key2 = oe->key2;
- index = HASH(key0, key1, key2, m);
- while (1) {
- ne = &nh[index];
- if (ne->key0 == NIL) {
- ne->key0 = oe->key0;
- ne->key1 = oe->key1;
- ne->key2 = oe->key2;
- ne->value = oe->value;
- break;
- } else {
- index++;
- if (index > m->maxIndex) index = 0;
- }
- }
- }
- free((char *)m->table);
- m->table = nh;
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- }
-
- int Map96_Lookup(m, key0, key1, key2)
- register Map96 m;
- register int key0, key1, key2;
- {
- register int index = HASH(key0, key1, key2, m);
- register TE96Ptr e;
- register int myNil = NIL;
- register int limit = m->maxIndex;
-
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- e = &m->table[index];
- while (1) {
- if (e->key0 == myNil) { /* we did not find it */
- return (myNil);
- } else if (e->key0 == key0 && e->key1 == key1 && e->key2 == key2) {
- return (e->value);
- }
- e++;
- if (++index > limit) {
- index = 0;
- e = &m->table[0];
- }
- }
- }
-
- #ifdef DO_REVERSE
- int Map96_InverseLookup(m, value)
- register Map96 m;
- register int value;
- /* do the inverse mapping; if ambiguous return any one of possible values */
- /* WARNING: Highly inefficient -- linear search */
- {
- register TE96Ptr e, last;
-
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- for (last = &m->table[m->maxIndex+1], e = &m->table[0]; e != last; e++) {
- if ((e->key != NIL) && (e->value == value)) return (e->key);
- }
- return ((int) NIL);
- }
- #endif DO_REVERSE
-
- void Map96_Delete(m, key0, key1, key2)
- register Map96 m;
- register int key0, key1, key2;
- /* Remove the entry, if it is there */
- {
- register int index = HASH(key0, key1, key2, m);
- register int value;
- register TE96Ptr e;
-
- while (1) {
- e = &m->table[index];
- if (e->key0 == NIL) { /* we did not find it */
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return;
- }
- if (e->key0 == key0 && e->key1 == key1 && e->key2 == key2) {
- /* Found it, now remove it */
- m->count--;
- e->key0 = NIL;
- e->value = NIL;
- #ifdef DEBUGMAP
- inhibitCheck = 1;
- #endif
- while (1) {
- /* rehash until we reach nil again */
- if (++index > m->maxIndex) index = 0;
- e = & m->table[index];
- key0 = e->key0;
- if (key0 == NIL) {
- #ifdef DEBUGMAP
- inhibitCheck = 0;
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return;
- }
- key1 = e->key1;
- key2 = e->key2;
- /* rehashing is done by removing then reinserting */
- value = e->value;
- e->key0 = e->value = NIL;
- m->count--;
- Map96_Insert(m, key0, key1, key2, value);
- }
- }
- if (++index > m->maxIndex) index = 0;
- }
- }
-
- void Map96_Insert(m, key0, key1, key2, value)
- register Map96 m;
- register int key0, key1, key2, value;
- {
- register int index;
- register TE96Ptr e;
- assert(key0 != NIL);
- if (m->count >= m->maxCount) ExpandHashTable(m);
- index = HASH(key0, key1, key2, m);
- while (1) {
- e = &m->table[index];
- if (e->key0 == NIL) { /* put it here */
- e->key0 = key0;
- e->key1 = key1;
- e->key2 = key2;
- e->value = value;
- m->count++;
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return;
- } else if (e->key0 == key0 && e->key1 == key1 && e->key2 == key2) {
- e->value = value;
- #ifdef DEBUGMAP
- CheckOutHashTable(m);
- #endif DEBUGMAP
- return;
- }
- if (++index > m->maxIndex) index = 0;
- }
- }
-
- int Map96_FindNext(m, startIndex, key0Ptr, key1Ptr, key2Ptr, valuePtr)
- register Map96 m;
- int *startIndex;
- int *key0Ptr, *key1Ptr, *key2Ptr, *valuePtr;
- {
- register int i;
- register TE96Ptr e;
- for (i = *startIndex; i <= m->maxIndex; i++) {
- e = &m->table[i];
- if (e->key0 != NIL) {
- *key0Ptr = e->key0;
- *key1Ptr = e->key1;
- *key2Ptr = e->key2;
- *valuePtr = e->value;
- *startIndex = i + 1;
- return(1);
- }
- }
- *key0Ptr = NIL;
- *key1Ptr = NIL;
- *key2Ptr = NIL;
- *valuePtr = NIL;
- *startIndex = -1;
- return(0);
- }
-
- void Map96_Print(m)
- register Map96 m;
- {
- int key0, key1, key2, value, index;
- printf(
- "\nDump of map96 @ 0x%05x, %d entr%s, current max %d\nIndex\tKey0\t\tKey1\t\tKey2\t\tValue\n",
- m, m->count, m->count == 1 ? "y" : "ies", m->maxCount);
- for (index = 0; index <= m->maxIndex; index++) {
- key0 = m->table[index].key0;
- key1 = m->table[index].key1;
- key2 = m->table[index].key2;
- value = m->table[index].value;
- printf("%3d\t0x%08.8x\t0x%08.8x\t0x%08.8x\t0x%08.8x\n", index,
- key0, key1, key2, value);
- }
- }
-
- static void CheckOutHashTable(m)
- register Map96 m;
- {
- register int i;
- register TE96Ptr realElement, e;
- register int index, firstIndex, count;
- count = 0;
-
- #ifdef DEBUGMAP
- if (inhibitCheck) return;
- #endif
- for (i = 0; i <= m->maxIndex; i++) {
- realElement = &m->table[i];
- if (realElement->key0 != NIL) {
- count++;
- index = HASH(realElement->key0, realElement->key1, realElement->key2, m);
- firstIndex = index;
- while (1) {
- e = &m->table[index];
- if (e->key0 == NIL) { /* we did not find it */
- break;
- } else if (e->key0 == realElement->key0 &&
- e->key1 == realElement->key1 &&
- e->key2 == realElement->key2) {
- break;
- } else {
- index++;
- if (index > m->maxIndex) index = 0;
- if (index == firstIndex) {
- index = -1;
- break;
- }
- }
- }
-
- if (index == -1 || !(e->key0 == realElement->key0 &&
- e->key1 == realElement->key1 &&
- e->key2 == realElement->key2)) {
- printf(
- "Map96 problem: Key 0x%x 0x%x 0x%x, rightI %d, realI %d probI %d value 0x%x\n",
- realElement->key0, realElement->key1, realElement->key2,
- firstIndex, i, index, realElement->value);
- Map96_Print(m);
- }
- }
- }
- if (count != m->count) {
- printf(
- "Map96 problem: Should have %d entries, but found %d.\n", m->count,
- count);
- Map96_Print(m);
- }
- }
-